package org.androbuzz;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.preference.PreferenceManager;
import android.util.Log;
import android.util.Pair;

public class AndroBuzzService extends Service{
	private static final long UPDATE_INTERVAL = 60000;
	private long curUpdateInterval = UPDATE_INTERVAL;
	private Timer timer = new Timer();
	private TimerTask timerTask = null;
	private NotificationManager osnotif = null;
	private static final int HELLO_ID = 1;
	private int nbClient = 0;
    private static final int REPORT_MSG = 1;
    private int nbNewBuzzIds = 0;
	private AndroBuzzDbAdapter mDbHelper;
	SharedPreferences config = null;
	private AndroBuzzAPIHandler mAPIHandler;
	
    final RemoteCallbackList<IAndroBuzzServiceCallback> mCallbacks
    = new RemoteCallbackList<IAndroBuzzServiceCallback>();
	
	public IBinder onBind(Intent intent) {
	        if (IAndroBuzzService.class.getName().equals(intent.getAction())) {
	            return mBinder;
	        }
	        
	        return null;
		}
	
	
	class BuzzComparator implements  Comparator<Pair<String, String>>
	{
		public int compare(Pair<String, String> o1, Pair<String, String> o2)
		{
			return o1.second.compareTo(o2.second);
		}
		
		public boolean equals(Object obj)
		{
	        if (!(obj instanceof BuzzComparator))
	            return false;
	        return true;
		}
	}
	
	@Override public void onCreate() {
		  super.onCreate();
		  
			mDbHelper = new AndroBuzzDbAdapter(this);
			mDbHelper.open();
			mAPIHandler = new AndroBuzzAPIHandler(this);
		  // init the service here
		  _startService();
	}
	
	@Override public void onDestroy() {
		  super.onDestroy();
		  mDbHelper.close();
		  _shutdownService();
		}

	
	private void _startService() {
		 osnotif = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
		 config = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
		 
		 curUpdateInterval =  Long.parseLong(config.getString("AndroBuzzUpdateInterval", String.valueOf(UPDATE_INTERVAL/1000)))*1000;
		 Log.i("service androbuzz", "timer set to: " + curUpdateInterval);
		 timerTask = new TimerTask() {
		        public void run() {
		        	_UpdateBuzz();
		        }
		 };
		 
		 timer.scheduleAtFixedRate(
				 timerTask,
		      0,
		      curUpdateInterval);
		 
		  mHandler.sendEmptyMessage(REPORT_MSG);
		  Log.i(getClass().getSimpleName(), "Timer started!!!");
		}
	
	private void _shutdownService() {
		  if (timer != null) timer.cancel();
		  
	        mCallbacks.kill();
	        
	        mHandler.removeMessages(REPORT_MSG);
	        
		  Log.i(getClass().getSimpleName(), "Timer stopped!!!");
		}
	
	private void changeTimer(long newTime)
	{
		 if(newTime !=  curUpdateInterval)
		 {
			 Log.i("service androbuzz", "timer set to: " + newTime);
			 curUpdateInterval =  newTime;
			 timerTask.cancel();
			 timer.purge();
			 
			 timerTask = new TimerTask() {
			        public void run() {
			        	_UpdateBuzz();
			        }
			 };
			 
			 timer.scheduleAtFixedRate(
					 timerTask,
				      0,
				      curUpdateInterval);
		 }		
	}
	
	private void createNotification()
	{
		int icon = R.drawable.ic_tab_feeds_co;
		CharSequence contentTitle = "AndroBuzz";
		CharSequence tickerText = "";
		CharSequence contentText = "";
		if(nbNewBuzzIds > 1)
		{
			tickerText = "New buzzes";
			contentText = "New buzzes (" + nbNewBuzzIds + ")";
		}
		else
		{
			tickerText = "New buzz";
			contentText = "New buzz";
		}
		
		long when = System.currentTimeMillis();
		Notification notification = new Notification(icon, tickerText, when);
		
		Context context = getApplicationContext();

		Intent notificationIntent = new Intent(this, AndroBuzzActivity.class);
		PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
			
		notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
		notification.flags |= Notification.FLAG_AUTO_CANCEL;
		notification.defaults |= Notification.DEFAULT_SOUND;

		if(config.getBoolean("Vibrate_notif", true) == true)
		{
			Log.i(getClass().getSimpleName(), "notification use vibration");
			long[] vibrate = {0,100,200,300};
			notification.vibrate = vibrate;
		}
		
		osnotif.notify(HELLO_ID, notification);	
	}
	
	/** dont forget to fire update to the ui listener */
	private void _UpdateBuzz() {
		Log.i(getClass().getSimpleName(), "Notif!!!");
		changeTimer(Long.parseLong(config.getString("AndroBuzzUpdateInterval", String.valueOf(UPDATE_INTERVAL/1000)))*1000);
		 
		GetNewBuzz();
		if(nbNewBuzzIds > 0)
		{
			if(nbClient == 0)
			{
				if(config.getBoolean("NotificationEta", true) == true)
				{
					createNotification();
				}
			}
			else
			{
				mHandler.sendEmptyMessage(REPORT_MSG);
			}
		}
	}
	
	private void GetNewBuzz()
	{
		nbNewBuzzIds = 0;
		AndroBuzzAccount account = new AndroBuzzAccount(getApplicationContext());
		Log.i(getClass().getSimpleName(), "Get string account.getUsername: " + account.getUsername());	
		ArrayList<String> accountList = new ArrayList<String>();
		accountList.add(account.getUsername());
		
		String curProfile = mDbHelper.findCurrentProfileId();
		if(curProfile.length() > 0)
		{
			Cursor curBuddies = mDbHelper.findBuddiesByName(curProfile);
			if (curBuddies.getCount() > 0) {
				curBuddies.moveToFirst();
				do {
					accountList.add(curBuddies.getString(curBuddies.getColumnIndex("email")).replace("@gmail.com", ""));
				}while (curBuddies.moveToNext());
			}
			curBuddies.close();
		}
		else
			Log.e(getClass().getSimpleName(), "Cannot get current profile in service !");
	/*	accountList.add("nboutinandrobuzz");
		accountList.add("nboutin90");*/
		//accountList.add("arnaud.l.dupuis");
		
		for(String username: accountList)
		{
			Log.i(getClass().getSimpleName(), "Get buzz for username: " + username);
			nbNewBuzzIds += mAPIHandler.retrieveBuzzAndComments(username);
		}
		
		Log.i(getClass().getSimpleName(), "Get buzz nb: " + nbNewBuzzIds);
		
		/*if(mBuzzIds.size() > 1)
			Collections.sort(mBuzzIds, new BuzzComparator());*/
	}
	

    /**
     * The IRemoteInterface is defined through IDL
     */
    private final IAndroBuzzService.Stub mBinder = new IAndroBuzzService.Stub() {
        public void registerCallback(IAndroBuzzServiceCallback cb) {
            if (cb != null)
        	{
	        	nbClient++;
	        	mCallbacks.register(cb);
        	}
        }
        public void unregisterCallback(IAndroBuzzServiceCallback cb) {

            if (cb != null)
        	{
            	nbClient--;
            	mCallbacks.unregister(cb);
        	}
        }
    };
	
    /**
     * Our Handler used to execute operations on the main thread.  This is used
     * to schedule increments of our value.
     */
    private final Handler mHandler = new Handler() {
        @Override public void handleMessage(Message msg) {
            switch (msg.what) {
                
                // It is time to bump the value!
                case REPORT_MSG: {
                    // Up it goes.
                    
                    // Broadcast to all clients the new value.
                    final int N = mCallbacks.beginBroadcast();
                    for (int i=0; i<N; i++) {
                    	//Log.i(getClass().getSimpleName(), "Send message!!!");
                        try {
                        	if(nbNewBuzzIds > 0)
                        	{
                        		/*Log.i(getClass().getSimpleName(), "Send message!!!");
                        		List<String> list = new ArrayList<String>();
                        		for(Pair<String, String> buzzId: mBuzzIds)
                        		{
                        			if(buzzId.second.length() > 0 && !list.contains(buzzId.second))
                        				list.add(buzzId.second);
                        		}
                    			mCallbacks.getBroadcastItem(i).newBuzz(list);   */  

                        		mCallbacks.getBroadcastItem(i).refreshOnNewBuzz();
                        	}
                        } catch (RemoteException e) {
                            // The RemoteCallbackList will take care of removing
                            // the dead object for us.
                        }
                    }
                    mCallbacks.finishBroadcast();
                    // Repeat every 1 second.
                    //sendMessageDelayed(obtainMessage(REPORT_MSG), 1*1000);
                } break;
                default:
                    super.handleMessage(msg);
            }
        }
    };
}
